/** for Serializable */
import java.io.Serializable;

/** for Arrays */
import java.util.Arrays;

/** for Random */
import java.util.Random;

/**
 * Planet class representing the planet in the Universe.
 * 
 * @version 1.0
 * @author Code Traders
 */
public class Planet implements Serializable {
	
	/**
	 * serialVersionUID for Planet class
	 */
	private static final long serialVersionUID = 844117581411470526L;
	
	/**
	 * Name of the Planet
	 */
	private final String name;
	
	/**
	 * Tech-level of the Planet
	 */
	private final Tech techLevel;
	
	/**
	 * Resource of the Planet
	 */
	private Resource resource;
	
	/**
	 * The point coordinate of the Planet
	 */
	private final Point point;
	
	/**
	 * The width and the height of the Planet
	 */
	private final int width, height;
	
	/**
	 * Life of Goods of the Planet
	 */
	private Goods[] goods = Goods.values();
	
	/**
	 * A random number generator
	 */
	private final Random rand = new Random();
	
	/** for FIVE **/
	private static final int FIVE = 5;
	
	/** for EIGHT **/
	private static final int EIGHT = 8;
	
	/** for TWELVE **/
	private static final int TWELVE = 12;

	/** for SEVENTEEN **/
	private static final int SEVENTEEN = 17;
	
	/** for TWENTY **/
	private static final int TWENTY = 20;
	
	/**
	 * Create Planet properties such as name, location,
	 *  Tech-level randomly generated, resources randomly generated.
	 *
	 * @param name
	 * @param x
	 * @param y
	 */
	public Planet (String name, int x, int y) {
		this.name = name;
		this.point = new Point(x, y);
		final int rand_tech = rand.nextInt(EIGHT);
		final int rand_resource = rand.nextInt(SEVENTEEN);
		this.techLevel = Tech.values()[rand_tech];
		this.resource = Resource.values()[rand_resource <= TWELVE ? rand_resource : 0];
		this.width = rand.nextInt(FIVE) + TWENTY;
		this.height = this.width;
		calcPrice();
	}
	
	/**
	 * This method is for calculating goods price and setting amounts of goods.
	 */
	private void calcPrice() {
		for (Goods g : goods) {
			g.setPlanet(this);
			g.calcPrice();
			g.calcInitialAmount();
		}
	}
	
	/**
	 * To handle and get location of a Planet
	 * @author Code Traders
	 */
	public static class Point implements Serializable {
		
		/**
		 * serialVersionUID for the Point class
		 */
		private static final long serialVersionUID = 1L;
		
		/**
		 * The x and the y values of the point
		 */
		private final int x, y;
		
		/**
		 * Point constructor
		 * @param x
		 * @param y
		 */
		public Point (int x, int y){
			this.x = x;
			this.y = y;
		}
		
		/**
		 * This is to get x coordinate
		 * @return x
		 */
		public int getX() {
			return this.x;
		}
		
		/**
		 * This is to get y coordinate
		 * @return y
		 */
		public int getY() {
			return this.y;
		}
		
		/**
		 * This is a tostring method.
		 * @return tostring.
		 */
		@Override
		public String toString() {
			return super.toString();
		}
	}
	
	/**
	 * To get Planet name
	 * @return name
	 */
	public String getName() {
		return this.name;
	}
	
	/**
	 * To get TechLevel
	 * @return TechLevel
	 */
	public Tech getTechLevel() {
		return this.techLevel;
	}
	
	/**
	 * To get Resource
	 * @return resource
	 */
	public Resource getResource() {
		return this.resource;
	}
	
	/**
	 * Setter for the Resource variable
	 * @param r Resource to set to
	 */
	public void setResource(Resource r) {
		this.resource = r;
	}
	
	/** 
	 * To get the location
	 * @return point
	 */
	public Point getPoint() {
		return this.point;
	}
	
	/** 
	 * To get the width
	 * @return width
	 */
	public int getWidth() {
		return this.width;
	}
	
	/** 
	 * To get the Height
	 * @return Height
	 */
	public int getHeight() {
		return this.height;
	}
	
	/**
	 * Getter for the array of Goods
	 * 
	 * @return array of Goods
	 */
	public Goods[] getGoods() {
		for (Goods g : this.goods) {
			g.setPlanet(this);
		}
		return this.goods;
	}
	
	/**
	 * Setter for the array of Goods
	 * 
	 * @param g array of Goods
	 */
	public void setGoods(Goods[] g) {
		this.goods = g.clone();
	}
	
	/** 
	 * This is a tostring method.
	 * @return tostring.
	 */
	@Override
	public String toString() {
		return this.name;
	}
	
	/**
	 * This is to check equals between planets
	 * @return true or false.
	 * @param obj
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == this) return true;
		final Planet planet = obj instanceof Planet ? (Planet) obj : null;
		return planet != null && this.name.equals(planet.name) 
				&& this.techLevel == planet.techLevel && this.resource == planet.resource 
				&& this.point.x == planet.point.x && this.point.y ==
				planet.point.y && this.width == planet.width 
				&& this.height == planet.height &&
				Arrays.equals(this.goods, planet.goods);
	}
	
	/**
	 * returns hashcode of the object
	 * 
	 * @return hash code of the object
	 */
	@Override
	public int hashCode() {
		return super.hashCode();
	}
}
